
package common.packet;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;

/**
 * Holds data about the current state of the world in the server.
 * Instances of this packet are frequently sent to all clients during the match.
 *
 * @author xissburg
 */
public class WorldState implements Packet
{
    private long latency;
    private Collection<BodyState> bodyStates;

    public WorldState() {
        this.bodyStates = null;
        latency = 0;
    }

    public WorldState(Collection<BodyState> bodyStates) {
        this.bodyStates = bodyStates;
        latency = 0;
    }

    public WorldState(DataInputStream in) throws IOException
    {
        this();
        read(in);
    }

    public WorldState(WorldState worldState)
    {
        bodyStates = new ArrayList<BodyState>();

        for(BodyState bs: worldState.getBodyStates())
            bodyStates.add(bs.copy());


        this.latency = worldState.latency;
    }

    public void read(DataInputStream in) throws IOException, IllegalArgumentException
    {
        latency = in.readLong();
        
        int entryCount = in.readInt();

        if(entryCount > 0)
        {
            bodyStates = new ArrayList<BodyState>();
            
            for(int i=0; i<entryCount; ++i)
            {
                Packet.Code c = Packet.Code.valueOf(in.readUTF());

                if(!c.equals(Packet.Code.BODY_STATE))
                    throw new IllegalArgumentException("BODY_STATE packet code expected.") ;

                BodyState bs = new BodyState(in);
                bodyStates.add(bs);
            }
        }
    }

    public void write(DataOutputStream out) throws IOException
    {
        out.writeUTF(getCode().name());

        out.writeLong(latency);

        if(bodyStates == null)
        {
            out.writeInt(0);
        }
        else
        {
            out.writeInt(bodyStates.size());

            for(BodyState bs: bodyStates)
                bs.write(out);
        }
    }

    public Code getCode() {
        return Code.WORLD_STATE;
    }

    public WorldState copy() {
        return new WorldState(this);
    }

    public Collection<BodyState> getBodyStates() {
        return bodyStates;
    }

    public void setBodyStates(Collection<BodyState> bodyStates) {
        this.bodyStates = bodyStates;
    }

    public long getLatency() {
        return latency;
    }

    public void setLatency(long latency) {
        this.latency = latency;
    }
}
